package network.handlers;

import java.io.IOException;

import state.Globals;
import state.group.GroupDispatcherState;
import managers.ElevatorManager;
import messages.BaseMessage;
import messages.GeneralAck;
import messages.MessageType;
import messages.registration.ElevatorRegistrationMessage;
import messages.registration.PersonDispatcherRegistrationMessage;
import network.BaseModeHandler;
import network.ConnectionMode;
import network.server.ModeHandlerThread;

public class RegistrationModeHandler extends BaseModeHandler {

    private int retryCount = 0;
    
    public RegistrationModeHandler(ModeHandlerThread parent)
    {
        super(parent);
    }

    @Override
    public ConnectionMode getMode()
    {
        return ConnectionMode.Registration;
    }

    @Override
    public boolean enterMode(byte id)
    {
    	Thread.currentThread().setName("Registration Handler " + Thread.currentThread().getId());
        return true;
    }

    @Override
    public void exitMode()
    {
        //NOOP
    }
    
    public ConnectionMode handleErr()
    {
        if (++retryCount == 3)
        {
            return ConnectionMode.Closed;
        }
        else
        {
            return ConnectionMode.Registration;
        }
    }

    @Override
    public ConnectionMode handleMessage(BaseMessage message)
    {
        if (message == null)
        {
            return handleErr();
        }
        switch (message.getMessageType())
        {
            case ElevatorRegistrationMessage:
                ElevatorRegistrationMessage eleReg = (ElevatorRegistrationMessage) message;
                
                parent.setClientId(eleReg.getClientId());
                
                return ConnectionMode.Elevator;
            case ObserverRegistrationMessage:
                
                return ConnectionMode.Observer;
            case PersonDispatcherRegistrationMessage:
                PersonDispatcherRegistrationMessage perReg = (PersonDispatcherRegistrationMessage) message;
                
                GroupDispatcherState state = ElevatorManager.getInstance().getDispatcherState();
                
                if (state.personDispatcherAddress == null)
                {
                    state.personDispatcherAddress = parent.getRemoteSocket().getInetAddress();
                    state.personDispatcherListeningPort = perReg.getListenPort();
                    
                    return ConnectionMode.PersonDispatcher;
                }
                else
                {
                    GeneralAck ack = new GeneralAck(MessageType.PersonDispatcherRegistrationMessage, false);
                    
                    try
                    {
                        parent.getRemoteSocket().getOutputStream().write(ack.toByteArray());
                    }
                    catch (IOException e)
                    {
                        Globals.getLogger().error("Error sending out failure ack on person dispatcher registration", e);
                    }
                    
                    return ConnectionMode.Closed;
                }
            case DeregistrationMessage:
                return ConnectionMode.Closed;
            default:
                return handleErr();
        }
    }

}
